Web 帐户管理器 |
您所在的位置:网站首页 › security accounts manager无法启用 › Web 帐户管理器 |
Web 帐户管理器
项目07/13/2023
本文介绍如何使用 AccountsSettingsPane 使用 Windows 10 和 Windows 11 Web 帐户管理器 API 将 通用 Windows 平台 (UWP) 应用连接到外部标识提供者(如 Microsoft 或 Facebook)。 你将了解如何请求用户的权限以使用其 Microsoft 帐户、获取访问令牌,并使用它来执行基本操作(如获取配置文件数据或将文件上传到他们的 OneDrive 帐户)。 相关步骤类似于通过支持 Web 帐户管理器的任何标识提供者来获取用户权限和访问权限。 注意 有关完整代码示例,请参阅 GitHub 上的 WebAccountManagement 示例。 准备工作首先,在 Visual Studio 中创建一个新的空白应用。 第二,你需要将你的应用与应用商店关联,以便连接到标识提供者。 若要执行此操作,请右键单击你的项目、依次选择“应用商店/发布”>“将应用与应用商店关联”,然后按照向导的说明进行操作。 第三,创建一个非常基本的 UI,由一个简单的 XAML 按钮和两个文本框组成。 并在代码隐藏中创建一个附加到按钮的事件处理程序: private void LoginButton_Click(object sender, RoutedEventArgs e) { }最后,添加以下命名空间,以便你以后无需担心任何引用问题: using System; using Windows.Security.Authentication.Web.Core; using Windows.System; using Windows.UI.ApplicationSettings; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.Data.Json; using Windows.UI.Xaml.Navigation; using Windows.Web.Http; 显示帐户设置窗格系统提供了一个名为 AccountsSettingsPane 的内置用户界面,用于管理标识提供者和 Web 帐户。 你可以按如下方式显示它: private void LoginButton_Click(object sender, RoutedEventArgs e) { AccountsSettingsPane.Show(); }如果你运行应用并单击“登录”按钮,应该会显示一个空窗口。 窗格为空的原因是系统只提供了一个 UI shell,这取决于开发人员是否使用标识提供者以编程方式填充窗格。 提示 或者,可以使用 ShowAddAccountAsync 而不是 Show,这会返回 IAsyncAction,用于查询操作的状态。 注册 AccountCommandsRequested若要向窗格添加命令,请先注册 AccountCommandsRequested 事件处理程序。 当用户要求查看窗格时(例如,单击 XAML 按钮),此事件处理程序将告知系统来运行生成逻辑。 在隐藏代码中,替代 OnNavigatedTo 和 OnNavigatedFrom 事件,并向它们添加以下代码: protected override void OnNavigatedTo(NavigationEventArgs e) { AccountsSettingsPane.GetForCurrentView().AccountCommandsRequested += BuildPaneAsync; } protected override void OnNavigatedFrom(NavigationEventArgs e) { AccountsSettingsPane.GetForCurrentView().AccountCommandsRequested -= BuildPaneAsync; }用户不会与帐户非常频繁地交互,因而以此种方式注册和取消注册事件处理程序有助于防止内存泄漏。 这样,当用户需要自定义窗格的可能性比较大时(例如,当他们在“设置”或“登录”页面时),自定义窗格只会在内存中。 生成帐户设置窗格只要显示 AccountsSettingsPane,就会调用 BuildPaneAsync 方法。 这是我们放置代码来自定义窗格中显示的命令的位置。 首先获取延迟。 这将告知系统延迟显示 AccountsSettingsPane,直到我们完成它的生成为止。 private async void BuildPaneAsync(AccountsSettingsPane s, AccountsSettingsPaneCommandsRequestedEventArgs e) { var deferral = e.GetDeferral(); deferral.Complete(); }接下来,使用 WebAuthenticationCoreManager.FindAccountProviderAsync 方法获取提供程序。 提供程序的 URL 因提供程序而异,并且可以在提供程序的文档中找到。 对于 Microsoft 帐户和 Azure Active Directory,应为 "https://login.microsoft.com"。 private async void BuildPaneAsync(AccountsSettingsPane s, AccountsSettingsPaneCommandsRequestedEventArgs e) { var deferral = e.GetDeferral(); var msaProvider = await WebAuthenticationCoreManager.FindAccountProviderAsync( "https://login.microsoft.com", "consumers"); deferral.Complete(); }请注意,我们还向可选 authority 参数传递字符串“consumers”。 这是因为 Microsoft 提供了两种不同类型的身份验证,即适用于“消费者”的 Microsoft 帐户 (MSA) 和适用于“组织”的 Azure Active Directory (AAD)。 “consumers”颁发机构指示我们需要 MSA 选项。 如果在开发一款企业应用,请使用“organizations”字符串。 最后,通过创建新的 WebAccountProviderCommand 将提供程序添加到 AccountsSettingsPane,如下所示: private async void BuildPaneAsync(AccountsSettingsPane s, AccountsSettingsPaneCommandsRequestedEventArgs e) { var deferral = e.GetDeferral(); var msaProvider = await WebAuthenticationCoreManager.FindAccountProviderAsync( "https://login.microsoft.com", "consumers"); var command = new WebAccountProviderCommand(msaProvider, GetMsaTokenAsync); e.WebAccountProviderCommands.Add(command); deferral.Complete(); }我们传递给新 WebAccountProviderCommand 的 GetMsaToken 方法尚不存在(我们将在下一步骤中生成该方法),因此当前可以将其作为空方法添加。 运行上述代码,你的窗格应当如下所示: 请求令牌“Microsoft 帐户”选项显示在 AccountsSettingsPane 中后,我们需要处理用户选择它时发生的情况。 我们注册了 GetMsaToken 方法,以便在用户选择使用其 Microsoft 帐户登录时触发,这样我们会在此时获得令牌。 若要获取令牌,请使用 RequestTokenAsync 方法,如下所示: private async void GetMsaTokenAsync(WebAccountProviderCommand command) { WebTokenRequest request = new WebTokenRequest(command.WebAccountProvider, "wl.basic"); WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request); }在此示例中,我们向作用域参数传递字符串“wl.basic”。 作用域表示你正在从提供给特定用户的服务请求的信息类型。 某些作用域仅提供对用户基本信息的访问权限,例如姓名和电子邮件地址,而其他作用域可能允许访问敏感信息,如用户的照片或电子邮件收件箱。 通常,应用应该至少使用实现其功能所必需的最小许可作用域。 有关需要哪些作用域才能获得用以与它们的服务结合使用的令牌,服务提供商将提供相关文档。 有关 Microsoft 365 和 Outlook.com 作用域,请参阅使用 Outlook REST API(版本 2.0)。 有关 OneDrive 的作用域,请参阅 OneDrive 身份验证和登录。提示 或者,如果应用程序使用登录提示(以使用默认电子邮件地址填充用户字段)或其他与登录体验相关的特殊属性,请将其列在 WebTokenRequest.AppProperties 属性中。 这将导致系统在缓存 Web 帐户时忽略该属性,进而避免缓存中的帐户不匹配。 如果在开发企业应用,可能需要连接到 Azure Active Directory (AAD) 实例,并使用 Microsoft Graph API,而非常规的 MSA 服务。 在此方案中,使用以下代码: private async void GetAadTokenAsync(WebAccountProviderCommand command) { string clientId = "your_guid_here"; // Obtain your clientId from the Azure Portal WebTokenRequest request = new WebTokenRequest(provider, "User.Read", clientId); request.Properties.Add("resource", "https://graph.microsoft.com"); WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request); }本文的剩余部分将继续介绍 MSA 方案,但 AAD 代码非常相似。 有关 AAD/Graph 的详细信息,包括 GitHub 上的完整示例,请参阅 Microsoft Graph 文档。 使用令牌RequestTokenAsync 方法会返回一个 WebTokenRequestResult 对象,它包含你请求的结果。 如果请求成功,它将包含一个令牌。 private async void GetMsaTokenAsync(WebAccountProviderCommand command) { WebTokenRequest request = new WebTokenRequest(command.WebAccountProvider, "wl.basic"); WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request); if (result.ResponseStatus == WebTokenRequestStatus.Success) { string token = result.ResponseData[0].Token; } }注意 如果在请求令牌时收到错误,请确保已将应用与 Microsoft Store 关联,如步骤一中所述。 如果你跳过此步骤,你的应用将无法获取令牌。 获得令牌后,可以使用它来调用提供商的 API。 在以下代码中,我们将调用用户信息 Microsoft Live API,以获取有关用户的基本信息并将其显示在我们的 UI 中。 但请注意,在大多数情况下,建议获取令牌后立即存储,然后以单独的方法使用该令牌。 private async void GetMsaTokenAsync(WebAccountProviderCommand command) { WebTokenRequest request = new WebTokenRequest(command.WebAccountProvider, "wl.basic"); WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request); if (result.ResponseStatus == WebTokenRequestStatus.Success) { string token = result.ResponseData[0].Token; var restApi = new Uri(@"https://apis.live.net/v5.0/me?access_token=" + token); using (var client = new HttpClient()) { var infoResult = await client.GetAsync(restApi); string content = await infoResult.Content.ReadAsStringAsync(); var jsonObject = JsonObject.Parse(content); string id = jsonObject["id"].GetString(); string name = jsonObject["name"].GetString(); UserIdTextBlock.Text = "Id: " + id; UserNameTextBlock.Text = "Name: " + name; } } }在提供程序之间,调用不同 REST API 的方式均不相同;有关如何使用令牌的信息,请参阅提供程序的 API 文档。 存储帐户以供将来使用令牌可用于立即获取有关用户的信息,但它们通常具有不同的生命期,例如,MSA 令牌的有效期只有几个小时。 幸运的是,每当令牌过期时,都不需要重新显示 AccountsSettingsPane。 在用户对你的应用进行一次授权后,你可以存储用户的帐户信息,以供将来使用。 若要执行此操作,请使用 WebAccount 类。 将以用于请求令牌的相同方法返回 WebAccount: private async void GetMsaTokenAsync(WebAccountProviderCommand command) { WebTokenRequest request = new WebTokenRequest(command.WebAccountProvider, "wl.basic"); WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request); if (result.ResponseStatus == WebTokenRequestStatus.Success) { WebAccount account = result.ResponseData[0].WebAccount; } }获得 WebAccount 实例后,即可轻松存储它。 在下面的示例中,我们使用 LocalSettings。 有关使用 LocalSettings 和其他方法来存储用户数据的详细信息,请参阅存储和检索应用设置和数据。 private async void StoreWebAccount(WebAccount account) { ApplicationData.Current.LocalSettings.Values["CurrentUserProviderId"] = account.WebAccountProvider.Id; ApplicationData.Current.LocalSettings.Values["CurrentUserId"] = account.Id; }然后,我们可以使用如下所示的异步方法,通过存储的 WebAccount 尝试在后台获取令牌。 private async Task GetTokenSilentlyAsync() { string providerId = ApplicationData.Current.LocalSettings.Values["CurrentUserProviderId"]?.ToString(); string accountId = ApplicationData.Current.LocalSettings.Values["CurrentUserId"]?.ToString(); if (null == providerId || null == accountId) { return null; } WebAccountProvider provider = await WebAuthenticationCoreManager.FindAccountProviderAsync(providerId); WebAccount account = await WebAuthenticationCoreManager.FindAccountAsync(provider, accountId); WebTokenRequest request = new WebTokenRequest(provider, "wl.basic"); WebTokenRequestResult result = await WebAuthenticationCoreManager.GetTokenSilentlyAsync(request, account); if (result.ResponseStatus == WebTokenRequestStatus.UserInteractionRequired) { // Unable to get a token silently - you'll need to show the UI return null; } else if (result.ResponseStatus == WebTokenRequestStatus.Success) { // Success return result.ResponseData[0].Token; } else { // Other error return null; } }将上述方法置于构建 AccountsSettingsPane 的代码之前。 如果已在后台获取令牌,则不需要显示该窗格。 private void LoginButton_Click(object sender, RoutedEventArgs e) { string silentToken = await GetMsaTokenSilentlyAsync(); if (silentToken != null) { // the token was obtained. store a reference to it or do something with it here. } else { // the token could not be obtained silently. Show the AccountsSettingsPane AccountsSettingsPane.Show(); } }由于采用静默方式获取令牌非常简单,所以你应该使用此过程来刷新会话之间的令牌,而不是缓存现有的令牌(因为令牌可能会随时过期)。 注意 上述示例中仅介绍了基本的成功和失败情况。 你的应用还应当考虑特殊情况(例如,用户吊销你的应用的权限或者从 Windows 中删除他们的帐户),并进行合理处理。 删除已存储帐户如果保留 web 帐户,你可能希望用户能够解除他们的帐户与你的应用之间的关联。 这样,他们可以有效地“注销”应用:他们的帐户信息将不再在启动时自动加载。 若要执行此操作,首先从存储中删除任何保存的帐户和提供商信息。 然后,调用 SignOutAsync 清除缓存,并使应用可能拥有的任何现有令牌失效。 private async Task SignOutAccountAsync(WebAccount account) { ApplicationData.Current.LocalSettings.Values.Remove("CurrentUserProviderId"); ApplicationData.Current.LocalSettings.Values.Remove("CurrentUserId"); account.SignOutAsync(); } 添加不支持 WebAccountManager 的提供程序如果你想要将身份验证从某个服务集成到你的应用中,但该服务不支持 WebAccountManager(例如 Google+ 或 Twitter),你仍可以将该提供程序手动添加到 AccountsSettingsPane。 若要执行此操作,请新建 WebAccountProvider 对象,并提供自己的名称和 .png 图标,然后将其添加到 WebAccountProviderCommands 列表。 下面是一些存根代码: private async void BuildPaneAsync(AccountsSettingsPane s, AccountsSettingsPaneCommandsRequestedEventArgs e) { // other code here var twitterProvider = new WebAccountProvider("twitter", "Twitter", new Uri(@"ms-appx:///Assets/twitter-auth-icon.png")); var twitterCmd = new WebAccountProviderCommand(twitterProvider, GetTwitterTokenAsync); e.WebAccountProviderCommands.Add(twitterCmd); // other code here } private async void GetTwitterTokenAsync(WebAccountProviderCommand command) { // Manually handle Twitter login here }注意 这只会将图标添加到 AccountsSettingsPane 并在单击该图标时运行指定的方法(在本例中为 GetTwitterTokenAsync)。 必须提供用于处理实际身份验证的代码。 有关详细信息,请参阅 Web 身份验证代理,它提供了使用 REST 服务进行身份验证的帮助程序方法。 添加自定义标题你可以使用 HeaderText 属性自定义帐户设置窗格,如下所示: private async void BuildPaneAsync(AccountsSettingsPane s, AccountsSettingsPaneCommandsRequestedEventArgs e) { // other code here args.HeaderText = "MyAwesomeApp works best if you're signed in."; // other code here }标题文本不要过于冗长;保持简洁明了。 如果你的登录过程很复杂并且需要显示详细信息,请使用自定义链接将用户链接到单独的页面。 添加自定义链接你可以向 AccountsSettingsPane 添加自定义命令,它们会在受支持的 WebAccountProviders 下方显示为链接。 自定义命令非常适合与用户帐户相关的简单任务,如显示隐私策略或为遇到问题的用户启动支持页面。 下面是一个示例: private async void BuildPaneAsync(AccountsSettingsPane s, AccountsSettingsPaneCommandsRequestedEventArgs e) { // other code here var settingsCmd = new SettingsCommand( "settings_privacy", "Privacy policy", async (x) => await Launcher.LaunchUriAsync(new Uri(@"https://privacy.microsoft.com/en-US/"))); e.Commands.Add(settingsCmd); // other code here }理论上,你可以对任何内容使用设置命令。 但是,我们建议将它们的使用范围限制在直观的与帐户相关的情况,如上文所述。 另请参阅Windows.Security.Authentication.Web.Core 命名空间 Windows.Security.Credentials 命名空间 AccountsSettingsPane 类 Web 身份验证代理 Web 帐户管理示例 Lunch Scheduler 应用 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |